package team.seekers.hula.question.answer.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import team.seekers.hula.common.entity.PageResult;
import team.seekers.hula.common.entity.VisibilityUpdateDTO;
import team.seekers.hula.auth.service.MindUtils;
import team.seekers.hula.question.answer.entity.dao.AnswerDO;
import team.seekers.hula.question.answerComment.service.AnswerCommentService;
import team.seekers.hula.record.mind.service.MindService;
import team.seekers.hula.question.point.service.PointService;
import team.seekers.hula.question.question.service.QuestionService;
import team.seekers.hula.user.user.entity.dao.UserDO;
import team.seekers.hula.question.answer.entity.dto.AnswerQueryDTO;
import team.seekers.hula.question.answer.entity.vo.AnswerManageListVO;
import team.seekers.hula.question.answer.entity.dto.AnswerAddDTO;
import team.seekers.hula.question.answer.entity.vo.AnswerInfoVO;
import team.seekers.hula.question.answer.entity.vo.AnswerListVO;
import team.seekers.hula.question.answer.entity.dto.AnswerUpdateDTO;
import team.seekers.hula.question.answer.mapper.AnswerMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import team.seekers.hula.user.userData.service.UserDataService;
import team.seekers.hula.user.userFollow.entity.vo.UserFollowInfoVO;
import team.seekers.hula.user.user.service.UserService;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 一个回答 服务实现类
 * </p>
 *
 * @author hbc
 * @since 2021-02-15
 */
@Service
public class AnswerService extends ServiceImpl<AnswerMapper, AnswerDO> {

    private boolean result;

    @Autowired
    @Lazy
    private UserService userService;

    @Autowired
    @Lazy
    private UserDataService userDataService;

    @Autowired
    @Lazy
    private MindService mindService;
    @Autowired
    @Lazy
    private QuestionService questionService;
    @Autowired
    @Lazy
    private PointService pointService;
    @Autowired
    @Lazy
    private AnswerCommentService answerCommentService;
    @Autowired
    @Lazy
    private AnswerGoodService answerGoodService;


    public String add(AnswerAddDTO answerAddDTO) {
        // 关键词审查


        // 新增回答
        AnswerDO answerDO = new AnswerDO();
        BeanUtils.copyProperties(answerAddDTO, answerDO);
        answerDO.setUserId(MindUtils.getUserId());
        save(answerDO);

        // 维护mind表，新增回答
        mindService.addAnswer(answerDO.getId(),answerDO.getVisibility());

        return answerDO.getId();
    }

    public void delete(String answerId) {
        //判断删的是不是自己的回答
        AnswerDO answerDO = getById(answerId);
        if (!MindUtils.isAdmin()) {
            if (!answerDO.getUserId().equals(MindUtils.getUserId())) {
                return;
            }
        }

        // 维护mind表
        mindService.deleteMindByLinkId(answerId);

        //删除回答下面所有的评论
        answerCommentService.deleteByAnswerId(answerId);

        //删除回答所有的赞
        answerGoodService.deleteByAnswerId(answerId);

        // 删除回答
        removeById(answerId);

    }

    public void updateInfo(AnswerUpdateDTO updateVO) {
        AnswerDO answerDO = getById(updateVO.getId());
        if (!MindUtils.isAdmin()){
            if(!answerDO.getUserId().equals(MindUtils.getUserId())){
                return;
            }
        }
        if(answerDO == null){
            return;
        }
        BeanUtils.copyProperties(updateVO, answerDO);
        updateById(answerDO);
    }

    public AnswerInfoVO get(String id,String userId) {
        AnswerDO answerDO = getById(id);
        if(answerDO == null){
            return null;
        }
        AnswerInfoVO answerInfoVO = new AnswerInfoVO();
        BeanUtils.copyProperties(answerDO,answerInfoVO);

        answerInfoVO.setIsLiked(answerGoodService.hasGood(id,userId));
        answerInfoVO.setIsMine(MindUtils.getUserId().equals(answerDO.getUserId()));

        UserFollowInfoVO infoVO = userService.getFollowInfoVO(answerDO.getUserId(),userId);
        answerInfoVO.setUserInfo(infoVO);

        return answerInfoVO;
    }

    public PageResult<AnswerListVO> page(AnswerQueryDTO answerQuery) {
        //首先更新热度
        updateAnswersHeatByPointId(answerQuery.getPointId());

        LambdaQueryChainWrapper<AnswerDO> wrapper = lambdaQuery().eq(AnswerDO::getPointId, answerQuery.getPointId());

        if(!StringUtils.isEmpty(answerQuery.getBegin())){
            wrapper.ge(AnswerDO::getGmtCreate,answerQuery.getBegin());
        }
        if (!StringUtils.isEmpty(answerQuery.getEnd())){
            wrapper.le(AnswerDO::getGmtCreate,answerQuery.getEnd());
        }

        switch (answerQuery.getOrderEnum()){
            case NEW:
                wrapper.orderByDesc(AnswerDO::getGmtCreate);
                break;
            case DEFAULT:
                wrapper.orderByDesc(AnswerDO::getHeat);
                break;
            case ME:
                wrapper.orderByDesc(AnswerDO::getHeat);
                wrapper.eq(AnswerDO::getUserId,MindUtils.getUserId());
                break;
        }

        Page<AnswerDO> page = wrapper.page(new Page<>(answerQuery.getPageNow(), answerQuery.getPageSize()));

        long total = page.getTotal();
        List<AnswerDO> records = page.getRecords();
        if(records == null){
            return null;
        }
        List<AnswerListVO> list = new ArrayList<>();
        for (AnswerDO record : records) {
            AnswerListVO answerListVO = new AnswerListVO();
            BeanUtils.copyProperties(record,answerListVO);
            UserDO userDO = userService.getById(record.getUserId());
            if(userDO == null){
                return null;
            }
            if(MindUtils.getUserId().equals(record.getUserId())){
                answerListVO.setIsMine(true);
            }
            answerListVO.setUserId(userDO.getId());
            answerListVO.setNickname(userDO.getNickname());
            answerListVO.setAvatar(userDO.getAvatar());
            list.add(answerListVO);
        }
        return new PageResult<>(total,list);
    }


    public void adminDelete(String answerId) {
        AnswerDO answerDO = getById(answerId);

        // 维护mind表
        mindService.deleteMindByLinkId(answerId);

        //删除回答下面所有的评论
        answerCommentService.deleteByAnswerId(answerId);

        //删除回答所有的赞
        answerGoodService.deleteByAnswerId(answerId);

        // 删除回答
        removeById(answerId);

    }

    public PageResult<AnswerManageListVO> adminPageOrderByTime(long current, long limit, AnswerQueryDTO answerQuery) {
        Page<AnswerQueryDTO> page = new Page<>(current,limit);
        IPage<AnswerManageListVO> list = baseMapper.pageAnswerCondition(page,answerQuery);
        List<AnswerManageListVO> records = list.getRecords();
        if(records == null)
            return null;
        long total = list.getTotal();

        Map<String,Object> map = new HashMap<>();
        map.put("total",total);
        map.put("rows",records);
        return new PageResult<>(total,records);
    }

    public List<AnswerManageListVO> getAllAdminAnswerInfo() {
        List<AnswerManageListVO> listAnswerVos = baseMapper.getAnswerInfo();
        return listAnswerVos;
    }


    //更新所有字段的heat值
    @Transactional(rollbackFor=Exception.class)
    public void updateAnswersHeatByPointId(String pointId){
        Date now=new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date currentDate = sdf.parse(sdf.format(now));
            QueryWrapper<AnswerDO> wrapper = new QueryWrapper<>();
            wrapper.eq("point_id",pointId);
            List<AnswerDO> answerDOList = baseMapper.selectList(wrapper);
            for(AnswerDO answerDO : answerDOList){
                String v = setAnswerHot(answerDO, currentDate);
                answerDO.setHeat(v);
                baseMapper.updateById(answerDO);
            }
        } catch (ParseException e){
            e.printStackTrace();
        }
    }

    //热度排行算法
    public String setAnswerHot(AnswerDO answerDO, Date currentDate) {
        Integer goodNumber = answerDO.getLikeCount();
        Integer commentNumber = answerDO.getCommentCount();
        Date gmtCreate = answerDO.getGmtCreate();
        float v = MindUtils.differentDaysByMillisecond(gmtCreate, currentDate);
        double heat = (goodNumber*3+commentNumber*5+1) / Math.pow((v + 2), 1.8);
        return heat+"";
    }

    public String addComment(String answerId) {
        AnswerDO answerDO = getById(answerId);
        answerDO.setCommentCount(answerDO.getCommentCount()+1);
        updateById(answerDO);
        return answerDO.getId();
    }

    public String addGood(String answerId) {
        AnswerDO answerDO = getById(answerId);
        answerDO.setLikeCount(answerDO.getLikeCount()+1);
        updateById(answerDO);
        return answerDO.getId();
    }

    public String reduceComment(String answerId) {
        AnswerDO answerDO = getById(answerId);
        answerDO.setCommentCount(answerDO.getCommentCount()-1);
        updateById(answerDO);
        return answerDO.getId();
    }

    public String reduceGood(String answerId) {
        AnswerDO answerDO = getById(answerId);
        answerDO.setLikeCount(answerDO.getLikeCount()-1);
        updateById(answerDO);
        return answerDO.getId();
    }


    public String getAnswerContent(String answerId) {
        return lambdaQuery().select(AnswerDO::getContent).eq(AnswerDO::getId,answerId).one().getContent();
    }

    public void updateVisibility(VisibilityUpdateDTO updateDTO) {
        lambdaUpdate().set(AnswerDO::getVisibility,updateDTO.getVisibility())
                .eq(AnswerDO::getId,updateDTO.getId())
                .update();

        mindService.updateVisibilityByLinkId(updateDTO.getId(),updateDTO.getVisibility());
    }

    public Integer countByQuestionId(String questionId) {
        return lambdaQuery().eq(AnswerDO::getQuestionId,questionId).count();
    }

    public Integer getAnswerCountByPointId(String pointId) {
        return lambdaQuery().eq(AnswerDO::getPointId,pointId).count();
    }
}
